#include "ThreadPool.h"
#include <iostream>
#include <thread>

using std::cout;
using std::endl;

ThreadPool::ThreadPool(size_t threadNum, size_t capa)
: _threadNum(threadNum)
, _threads()
, _capacity(capa)
, _taskQue(_capacity)
, _isExit(false)
{
}

ThreadPool::~ThreadPool()
{
}

//线程池的启动与停止
void ThreadPool::start()
{
    for(size_t idx = 0; idx < _threadNum; ++idx)
    {
        //创建线程，然后启动线程，并且存放在vector
        _threads.push_back(thread(&ThreadPool::doTask, this));
    }
}

void ThreadPool::stop()
{
    //先判断任务队列是不是为空，如果为空就不向下执行，这样肯定
    //可以保证任务执行完毕
    while(!_taskQue.empty())
    {
        //如果主线程抢夺的CPU的控制权，就应该让其放弃CPU的控制
        //不然CPU在此处就是空转（什么事都不做）
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }
    //更改线程池退出的标志位
    _isExit = true;
    //将所有等待在_notEmpty条件变量上的线程，也就是工作线程
    //（子线程唤醒）
    _taskQue.wakeup();

    //回收子线程（让线程等待子线程的执行）
    for(auto &th : _threads)
    {
        th.join();
    }
}

//添加任务与获取任务
void ThreadPool::addTask(Task &&task)
{
    if(task)
    {
        _taskQue.push(std::move(task));
    }
}

Task ThreadPool::getTask()
{
    return _taskQue.pop();
}

//线程池交给工作线程执行的任务(线程入口函数)
void ThreadPool::doTask()
{
    //只要线程池不退出，就应该一直执行任务
    while(!_isExit)
    {
        //先获取任务，然后执行任务
        Task taskcb = getTask();
        if(taskcb)
        {
            /* taskcb->process();//多态 */
            taskcb();//回调函数的执行
        }
        else
        {
            cout << "nullptr == taskcb" << endl;
        }
    }
}
